<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Contact;
use App\Models\Group;
use App\Models\Category;
use App\Models\SubCategory;
use App\Models\DataExcel;
use App\Http\Requests\ContactRequest;
use App\Http\Requests\ContactDatabaseRequest;
use App\Http\Requests\UploadContactExcel;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Requests\UploadDataExcel;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Collection;
use App\Rules\phoneRole;

class ContactController extends Controller
{
    public function index()
    {
        $contacts = Contact::paginate(8);
        $groups = Group::all();
        return view('dashboard.contacts.index',compact('contacts','groups'));
    }
    public function create()
    {
        return view('dashboard.contacts.add');
    }

    public function store(Request $request)
    {
        $request->validate([
            'phones' => 'required|string',
            'names' => 'nullable|string',
            'group_id' => 'required|exists:groups,id',
        ]);
    
        $rawPhones = preg_split('/[\r\n,]+/', $request->phones);
        $rawNames = preg_split('/[\r\n]+/', $request->names);
    
        $invalidPhones = [];
        $duplicates = [];
    
        $cleanPhones = collect($rawPhones)->map(function ($phone) {
            return trim($phone);
        })->filter(fn($p) => strlen($p) >= 8)->values();
    
        $cleanNames = collect($rawNames)->map(fn($name) => trim($name))->values();
    
        foreach ($cleanPhones as $i => $phone) {
            $name = $cleanNames[$i] ?? null;
            if (!preg_match('/^\+?\d+$/', $phone)) {
                $invalidPhones[] = $phone;
                continue;
            }
    
            if (Contact::where('phone', $phone)->exists()) {
                $duplicates[] = $phone;
                continue;
            }
    
            Contact::create([
                'phone' => $phone,
                'name' => $name,
                'group_id' => $request->group_id,
            ]);
        }
    
        if (!empty($invalidPhones)) {
            return redirect()->back()
                ->withInput()
                ->withErrors([
                    'phones' => 'Invalid phone format: ' . implode(', ', $invalidPhones) .
                                '. Only digits are allowed, optionally starting with + (e.g. +123456789 or 0123456789).',
                ]);
        }
    
        if (!empty($duplicates)) {
            return redirect()->back()
                ->withInput()
                ->withErrors([
                    'phones' => 'These numbers already exist: ' . implode(', ', $duplicates),
                ]);
        }
    
        toastr()->success('Contacts saved successfully');
        return redirect()->route('contacts.index');
    }
    
    
    public function storeFromDatabase(Request $request)
    {
        if(!$request->phones)
        {
            return redirect()->back()
                ->withInput()
                ->withErrors(['phones' => 'Numbers Are required']);
        }
    
        $phones = DataExcel::whereIn('id', $request->phones)->get();
    
        $existingNumbers = [];
        $newContacts = [];
    
        foreach ($phones as $phone) {
            $exists = Contact::where('phone', $phone->phone)->exists();
    
            if ($exists) {
                $existingNumbers[] = $phone->phone;
            } else {
                $newContacts[] = [
                    'phone' => $phone->phone,
                    'name' => $phone->name,
                    'group_id' => $request->group_id,
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }
        }
    
        if (!empty($existingNumbers)) {
            return redirect()->back()
                ->withInput()
                ->withErrors(['phones' => 'These numbers already exist: ' . implode(', ', $existingNumbers)]);
        }
    
        Contact::insert($newContacts);
    
        toastr()->success('Data saved from database successfully!');
        return redirect()->route('contacts.index');
    }
    

    public function storeFromExcel(UploadContactExcel $request)
    {
        if (!$request->hasFile('file'))
        {
            toastr()->error('Please upload at least one file.');
            return redirect()->back();
        }

        $files = $request->file('file');
        $invalidData = [];

        try {
            foreach ($files as $file)
            {
                $fileName = time() . '-' . uniqid() . '.' . $file->getClientOriginalExtension();
                $destinationPath = storage_path('Contacts/contacts_files/');
                if (!file_exists($destinationPath)) {
                    mkdir($destinationPath, 0777, true);
                }
    
                $file->move($destinationPath, $fileName);
                $filePath = $destinationPath . $fileName;
    
                $rows = Excel::toArray(null, $filePath)[0];
    
                if (empty($rows) || count($rows) < 2) {
                    toastr()->error('The uploaded Excel file is empty or has no data.');
                    return redirect()->back();
                }
    
                $originalHeaders = array_map(fn($header) => strtolower(trim(preg_replace('/\s+/', '', $header))), $rows[0]);
    
                $headerMap = [
                    'phone' => ['phone','telephone','mobile','تليفون','موبايل','هاتف','جوال'],
                ];
                $normalizedHeaders = [];
                foreach ($headerMap as $key => $aliases) {
                    foreach ($aliases as $alias) {
                        $cleaned = strtolower(trim(preg_replace('/\s+/', '', $alias)));
                        if (($index = array_search($cleaned, $originalHeaders)) !== false) {
                            $normalizedHeaders[$key][] = $index;
                        }
                    }
                }
    
                for ($i = 1; $i < count($rows); $i++) {
                    $row = array_map(fn($v) => trim(preg_replace('/\s+/', '', $v)), $rows[$i]);
                    $rowAssoc = [];
    
                    foreach ($normalizedHeaders as $field => $indexes) {
                        $values = array_map(fn($i) => $row[$i] ?? null, $indexes);
                        if ($field === 'phone') {
                            $rowAssoc[$field] = trim(implode(' ', array_filter($values)));
                        } else {
                            $rowAssoc[$field] = $values[0] ?? null;
                        }
                    }
    
                    if (!array_filter($rowAssoc)) continue;
                    $rowAssoc['phone'] = preg_replace('/\s+/', '', $rowAssoc['phone'] ?? '');

                    $isValidPhone = fn($num) => preg_match('/^\+?\d+$/', $num);

                    $cleanPhone = $isValidPhone($rowAssoc['phone']) ? $rowAssoc['phone'] : null;
                    if ($cleanPhone === null) {
                        $rejectionReason[] = 'Invalid phones';
                        $rowAssoc['rejection_reason'] = implode(', ', $rejectionReason);
                        $invalidData[] = $rowAssoc;
                        continue;
                    }

                    if ($cleanPhone === null) {
                        $rowAssoc['phone'] = null;
                    }

                    $exists = Contact::where('phone', $cleanPhone)->exists();
    
                    if ($exists) {
                        toastr()->error('This data already exists!');
                        return redirect()->back();
                    }
                    $dataExcel = Contact::updateOrCreate([
                        'phone' => $cleanPhone,
                        'group_id'=>$request->group_id
                    ]);
                }
            }
    
            if (!empty($invalidData)) {
                session()->put('invalidData', $invalidData);
                toastr()->warning('Import done with some invalid data. You can download the invalid data file.');
                return redirect()->route('contacts.index')->with('showDownloadButton', true);
            }
    
           
         toastr()->success('Phones are saved successfully');
         return redirect()->route('contacts.index');
    
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'error' => 'Error importing data: ' . $e->getMessage(),
            ], 500);
        }
    }

    public function downloadInvalidDataReport()
 { 
    $invalidData = session()->get('invalidData', []);
    
    if (empty($invalidData)) {
        toastr()->error('No invalid data to download.');
        return redirect()->route('contacts.index');
    }
    $headers = [
        'phone' => 'Phone',
        'rejection_reason' => 'Rejection Reason'
    ];
    $response = new StreamedResponse(function () use ($invalidData, $headers) {
        $output = fopen('php://output', 'w');
        fputcsv($output, array_values($headers));
        foreach ($invalidData as $row) {
            $data = [
                $row['phone'] ?? '',
                $row['rejection_reason'] ?? ''
            ];
            fputcsv($output, $data);
        }

        fclose($output);
    });
    $response->headers->set('Content-Type', 'text/csv');
    $response->headers->set('Content-Disposition', 'attachment; filename="invalid_data_report.csv"');

    return $response;
 }

    public function show($id)
    {
       
    }
    public function edit($id)
    {
       $contact = Contact::findOrFail($id);
       $groups = Group::all();
       return view('dashboard.contacts.edit',compact('contact','groups'));
    }
    public function create_new_contact()
    {
        
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request,$id)
    {
       $contact = Contact::findOrFail($id);
       $contact->phone = $request->phone;
       $contact->name = $request->name;
       $contact->group_id = $request->group_id;
       $contact->save();

       toastr()->success('Phone are Updated successfully');
       return redirect()->route('contacts.index');

    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Request $request)
    {
        Contact::where('id',$request->id)->delete();
        toastr()->success('Data of Excel are Deleted successfully');
        return redirect()->route('contacts.index');

    }

    public function delete_all(Request $request)
    {
       
        $delete_all_id = explode(",", $request->delete_all_id);
        Contact::whereIn('id', $delete_all_id)->Delete();
        toastr()->success('the Rows that you choosed are deleted successfully');
        return redirect()->route('contacts.index');
    }

    public function search(Request $request)
{
    $query = $request->get('query');

    $contacts = Contact::where('phone', 'like', "%{$query}%")
        ->orWhere('name', 'like', "%{$query}%")
        ->orderBy('id', 'desc')
        ->get();

    return response()->json($contacts);
}

public function groupContacts(Group $group)
{
    $contacts = Contact::where('group_id',$group->id)->paginate(8);
    return view('dashboard.contacts.contacts', compact('contacts','group'));
}
public function contacts(Request $request, $id)
    {
        $data['groupId'] = $id;
        $data['countries'] = DataExcel::pluck('country');
        $data['phonesExcel'] = DataExcel::all();
        $data['categories'] = Category::all();
        $data['subcategories'] = SubCategory::all();
        return view('dashboard.contacts.new_contact_with_group',$data);
    }
    
public function create_contacts(Group $group)
    {
        return view('dashboard.contacts.contacts',compact('group'));
    }

    public function getSubcategories($categoryId)
    {
        $subcategories = SubCategory::where('category_id', $categoryId)->get();
        return response()->json($subcategories);
    }
    
    public function filterPhones(Request $request)
    {
        $query = DataExcel::query();

    if ($request->category_id) {
        $query->where('category_id', $request->category_id);
    }

    if ($request->subcategory_id) {
        $query->where('subcategory_id', $request->subcategory_id);
    }

    if ($request->country) {
        $query->where('country', $request->country);
    }

    $phones = $query->pluck('phone')->unique()->toArray();

    return response()->json($phones);
    }
}